import {
  connectorRuleFormToConnectorOptionsFieldOption,
  ConnectorOptionsFieldOptionToConnectorRuleForm
} from '@src/modules/connector/util/card';
// import { uuid } from 'pub-bbx-utils';
import { uuid } from '@src/util/lang/string'
import { message } from '@src/util/message'
/* util */
import { connectorToField2FormField } from '@src/modules/connector/util/form'
import { isArray, isEmpty } from '@src/util/type';
import { t } from '@src/locales';
/* model */
import { ConnectorFieldTypeEnum } from '@src/modules/connector/model';
import { cloneDeep, isFunction } from 'lodash';
import { ConnectorOptionsActionEnum } from 'src/modules/connector/model/enum'

function findItem(treeData, id) {
  if (id == 0 || !treeData) return null;
  if (treeData.uniqueId == id) return treeData;
  let findAfterItem = null
  if (treeData.childNodes && treeData.childNodes.length) {
    for (let i = 0; i < treeData.childNodes.length; i++) {
      if (treeData.childNodes[i].uniqueId === id) {
        findAfterItem = treeData.childNodes[i];
        break
      }
      findAfterItem = findItem(treeData.childNodes[i], id);
      if(findAfterItem) return findAfterItem
    }
  }
  return findAfterItem
}

// 通过id查找node
function getNodeById(data, id) {
  return findItem(data, id);
}

// 打平node数据
function formatNodeData(arr, treeData) {
  if (!treeData) return null;
  const fieldOptions = {};
  if (treeData.data?.executeAction?.paasNodeId) {
    fieldOptions.paasNodeId = treeData.data.executeAction.paasNodeId;
  }
  if (treeData.type == 0 || treeData.type == 3 || treeData.type == 4 || treeData.type == 6) {
    arr.push({
      id: treeData.id,
      uniqueId: treeData.uniqueId,
      bizType:
        treeData.type == 4 ? 'MESSAGE' : treeData.type == 6 ? 'CODE' : treeData.data?.bizType || '',
      bizTypeId: treeData.type == 4 ? '0' : treeData.data?.bizTypeId || '',
      bizTypeName:
        treeData.type == 4 ? t('common.base.messageNotification')  : treeData.type == 6 ? '执行代码' :  treeData.data?.name || '',
      bizTypeLogo: treeData.type == 4 ? '' : treeData.data?.logo || '',
      isStart: treeData.type == 0,
      fieldOptions: fieldOptions,
    });
  }
  if (treeData.childNodes && treeData.childNodes.length) {
    for (let i = 0; i < treeData.childNodes.length; i++) {
      formatNodeData(arr, treeData.childNodes[i]);
    }
  }
}

// 打平line数据
function formatLineData(arr, treeData, executeActionApplicationFieldsMap) {

  if (!treeData) return null;
  if (treeData.type == 2) {
    let convertType = treeData.data?.convertType || 'fieldMapping';
    let conditionList = treeData.data.conditionList.map(conditionArr => {
        return (conditionArr || []).filter(item=>{return item.leftFieldValue}).map(item => {
          return connectorRuleFormToConnectorOptionsFieldOption(item, true);
        });
      });
    let convertCode = treeData.data?.convertCode || '';
    
    let executeAction = treeData.childNodes[0].data.executeAction || {};
    if(treeData.childNodes[0].type === 4 || treeData.childNodes[0].type === 6) {
      // 获取消息配置参数
      executeAction = treeData.childNodes[0].data || {}
    }
    const { action, apiId, javaCode, mappingType } = executeAction
    const defaultFieldOptions = treeData.childNodes[0].data?.defaultToNodeData?.fieldOptions || {}
    let transformEA = {
      // 消息的action固定是MESSAGE
      action: treeData.childNodes[0].type === 4 ? 'MESSAGE' : treeData.childNodes[0].type === 6 ? 'CODE' : action,
      apiId,
      executeMethod: executeAction.executeMethod,
      javaCode,
      mappingType,
      insertFieldOptions: function() {
        const result = (executeAction?.insertFieldOptions || []).filter(item=>{return item.leftFieldValue}).map(
          item => {

            if (!item?.field || isEmpty(item?.field)) {
              item.field = executeActionApplicationFieldsMap[item?.leftFieldValue] || {}
            }

            return {
              ...connectorRuleFormToConnectorOptionsFieldOption(item, false),
              parentEnName: item.parentEnName,
            }

          }
        )
        return result.length ? result : defaultFieldOptions?.insert
      }(),
      updateFieldOptions: {
        select: function() {
          const result = (executeAction?.updateFieldOptions?.select || []).filter(item=>{return item.leftFieldValue}).map(item => {

            if (!item?.field || isEmpty(item?.field)) {
              item.field = executeActionApplicationFieldsMap[item?.leftFieldValue] || {}
            }

            return connectorRuleFormToConnectorOptionsFieldOption(item, true);
          })
          return result.length ? result : defaultFieldOptions?.select
        }(),
        update: function() {
          const result = (executeAction?.updateFieldOptions?.update || []).filter(item=>{return item.leftFieldValue}).map(item => {

            if (!item?.field || isEmpty(item?.field)) {
              item.field = executeActionApplicationFieldsMap[item?.leftFieldValue] || {}
            }

            return connectorRuleFormToConnectorOptionsFieldOption(item, false);
          })
          return result.length ? result : defaultFieldOptions?.update
        }(),
      },
      deleteFieldOptions:{
        message:{
          paasReceiver:JSON.stringify(executeAction?.deleteFieldOptions?.message?.paasReceiver)
        },
        delete: function() {
          const result = (executeAction?.deleteFieldOptions?.delete || []).filter(item=>{return item.leftFieldValue}).map(item => {

            if (!item?.field || isEmpty(item?.field)) {
              item.field = executeActionApplicationFieldsMap[item?.leftFieldValue] || {}
            }

            return connectorRuleFormToConnectorOptionsFieldOption(item, true);
          })
          return result.length ? result : defaultFieldOptions?.delete
        }()
      },
      // 后端需要的消息配置参数
      messageConfigOptions: executeAction,
      codeConfigOptions: executeAction,
    };
    arr.push({
      id: treeData.id,
      name: treeData.data.name,
      convertType,
      conditionList,
      convertCode,
      from: treeData.getParent().isTrigger
        ? treeData.getParent().getParent().uniqueId
        : treeData.getParent().uniqueId,
      to: treeData.childNodes[0].uniqueId,
      executeAction: transformEA,
    });
  }
  if (treeData.childNodes && treeData.childNodes.length) {
    for (let i = 0; i < treeData.childNodes.length; i++) {
      formatLineData(arr, treeData.childNodes[i], executeActionApplicationFieldsMap);
    }
  }
}
// 服务端表单数据转连接器组件
export function transformServeVlaue(arr = [], fieldList, isSelect) {
  let result = []

  arr.forEach(item => {

    // 放到组件里去转换了
    // if(item?.valueType === 3) {
    //   item.value = item.value.map(item=> convertTriggerAppFormFieldValue(item, isSelect, true, fieldList))
    // }

    const parent = item.toEnName.split('.').shift()
    const current = item.toEnName.split('.').pop()
    if (current != item.toEnName) {
      item.toEnName = current
      const res = ConnectorOptionsFieldOptionToConnectorRuleForm(item, fieldList.find(item => {return item.enName === parent}).children || null, isSelect)
      res.enName = parent + '.' + current
      res.leftFieldValue = parent + '.' + current
      result.push(res)
    } else {
      result.push(ConnectorOptionsFieldOptionToConnectorRuleForm(item, fieldList, isSelect))
    }
    
    // 子字段
    const subFields = fieldList.filter(f => f.parentEnName === item.toEnName)

    if (subFields.length) {
      let relationShip = {}

      try {
        let parentValue = JSON.parse(item?.value[0] || '')

        relationShip = parentValue?.relationShip || {}

      } catch(err) {
        console.error('transformServeVlaue error: ', err)
      }

      // 子值
      let subValues = []

      subFields.forEach(field => {
        // 还原拼接前的fieldName
        const originFieldName = field.enName.replace(`${item.toEnName}-`, '');

        let { valueType = 2, value = '' } = relationShip[originFieldName] || {}

        subValues.push({
          toEnName: field.enName,
          valueType,
          value: [value],
          operate: null,
        })
      })

      subValues = subValues.map(sub => ConnectorOptionsFieldOptionToConnectorRuleForm(sub, fieldList, isSelect))

      result = result.concat(...subValues)
    }
  })

  return result.filter(item =>{
    return !item.componentName || (item.componentName && item.componentName != '-search')
  })
}

// 前端数据转服务端
async function toServeData(treeData, serverTriggerInfo) {

  let nodeList = [];
  let lineList = [];

  let executeActionApplicationFieldsMap = {}

  try {

    const executeActionApplicationFields = getExecuteActionApplicationFieldsByServerTriggerInfo(serverTriggerInfo)

    executeActionApplicationFieldsMap = getExecuteActionApplicationFieldsMap(executeActionApplicationFields)

  } catch (error) {
    console.warn(error)
  }

  await formatNodeData(nodeList, treeData);
  await formatLineData(lineList, treeData, executeActionApplicationFieldsMap);

  return {
    nodeList,
    lineList,
  };
}

function getExecuteActionApplicationFieldsByServerTriggerInfo(serverTriggerInfo) {

  try {

    const triggerInfo = serverTriggerInfo || {}
    const nodeList = triggerInfo?.nodeList || []
    const lineList = triggerInfo?.lineList || []

    let fieldList = []

    nodeList.forEach(node => {

      const isStart = node?.isStart

      if (isStart) {
        return
      }

      fieldList = fieldList.concat(node?.fieldList || [])

    })

    return fieldList

  } catch (error) {

    console.warn(error)

    return []

  }

}

function getExecuteActionApplicationFieldsMap(fields) {
  return (
    fields.reduce((prev, current) => {
      prev[current.enName] = connectorToField2FormField(current);
      return prev;
    }, {})
  )
}

// 服务端数据转前端
function transformTreeData(triggerInfo, conditionFieldList, actionAppFieldList) {
  let nodeConfig = {};
  let nodeList = triggerInfo.nodeList || [];
  let lineList = triggerInfo.lineList || [];
  let startApp = nodeList.find(item => {
    return item.isStart;
  });

  const options = (isArray(triggerInfo?.executeWay?.options) ? triggerInfo?.executeWay?.options?.[0] : triggerInfo?.executeWay?.options) || {};
  nodeConfig = {
    nodeName: t('common.connector.trigger.startApp'),
    type: 0,
    isStart: true,
    uniqueId: startApp.uniqueId,
    id: startApp.id,
    parentId: 0,
    childNodes: [],
    data: {
      appId: startApp.appId,
      appBizType: startApp.bizType,
      inside: true,
      name: `${startApp.bizTypeName }/${ startApp.apiName}`,
      logo: startApp.bizTypeLogo,
      bizType: 'api',
      bizTypeId: startApp.apiId,
      bizTypeAndId: `api,${startApp.apiId}`,

      bizActionCode: `${options?.paasNodeId ? `${options?.paasNodeId}/` : ''}${triggerInfo?.executeWay?.way === 'timer' || triggerInfo?.executeWay?.way === 'manual' || triggerInfo?.executeWay?.way === 'event' || triggerInfo?.executeWay?.way === 'timeOutPlus' ?  triggerInfo?.executeWay?.way : (options?.action || 'webhook')}`,
      bizActionName: options?.actionName || triggerInfo?.executeWay?.wayName,
      url: options?.url,
      paasNodeId: options?.paasNodeId || '',
      timerOptions: (triggerInfo?.executeWay?.way === 'timer' ? options : {}),
      rule: (triggerInfo?.executeWay?.way === 'timeOutPlus' ? options.rule : {}),
      timeOutType: options?.timeOutType || 'duration',
      eventOptionList: (triggerInfo?.executeWay?.options || []).map(x => ({...x, action : x.paasNodeId ? x.paasNodeId + '/'+ x.action : x.action}) ),
      ...(triggerInfo?.executeWay?.way === 'timer' ? options : {})
    },
  };


  const traverseNode = (nodeConfig, lineList, nodeList)=> {
    const currentNodeConfigFromLine = lineList.filter(item=> item.from === nodeConfig.uniqueId)

    if(currentNodeConfigFromLine.length > 0) {
      for(let i = 0; i < currentNodeConfigFromLine.length; i++) {
        const line = currentNodeConfigFromLine[i]
        const toNode = nodeList.find(item=> line.to === item.uniqueId)
        const insertNodeData = insertNode(toNode, nodeConfig, line)
        nodeConfig.childNodes.push(insertNodeData)

        const toNodeFromLine = lineList.filter(item=> toNode.uniqueId === item.from)
        if(toNodeFromLine.length !== 0) {
          insertNodeData.childNodes = [traverseNode(insertNodeData.childNodes[0], lineList, nodeList)]
        }
      }

    }
    return cloneDeep(nodeConfig)
  }

  traverseNode(nodeConfig, lineList, nodeList)

  return nodeConfig;
}

const insertNode = (toNode, nodeConfig, item)=> {
  const newUuid = uuid()
  const nodeItem = {
    nodeName: t('common.connector.title.condition'),
    type: 2,
    uniqueId: newUuid,
    id: item?.id || null,
    parentId: nodeConfig.uniqueId,
    isEdit: true,
    data: {
      name: item.name,
      conditionList: function() {
        const defaultConditionList = item.conditionList || []
        if(defaultConditionList.length === 0) return [[]]
        return defaultConditionList.map(condition => {
          return transformServeVlaue(condition, item?.allFromFieldList || [], true)
        })
      }(),
      convertType: item?.convertType,
      convertCode: item?.convertCode,
    },
    childNodes: [
      {
        nodeName: toNode.action == 'MESSAGE' ? t('common.base.messageNotification') : toNode.action == 'CODE' ? '执行代码' : t('common.connector.trigger.executeApp'),
        type: toNode.action == 'MESSAGE' ? 4 : toNode.action == 'CODE' ? 6 : 3,
        id: toNode.id || null,
        uniqueId: toNode.uniqueId,
        parentId: newUuid,
        childNodes: [],
        isEdit: true,
        data: toNode.action == 'MESSAGE' || toNode.action == 'CODE' ? toNode?.fieldOptions : {
          defaultToNodeData: {...toNode},
          appId: toNode.appId,
          name: `${toNode.bizTypeName}/${toNode.apiName}`,
          logo: toNode.bizTypeLogo,
          bizType: 'api',
          bizTypeId: toNode.apiId,
          bizTypeAndId: `api,${toNode.apiId}`,
          executeAction:{
            javaCode: getServerJavaCode(toNode?.action, toNode?.fieldOptions),
            mappingType: toNode?.mappingType || 'fieldRelation',
            inside: toNode?.inside || true,
            action: toNode?.action || '',
            apiId: toNode?.apiId || '',
            executeMethod: toNode?.executeMethod || 2,
            insertFieldOptions: [],
            updateFieldOptions:{
              select: [],
              update: [],
            },
            deleteFieldOptions:{
              delete: [],
              message:{
                paasReceiver: toNode?.fieldOptions?.message?.paasReceiver ? JSON.parse(toNode?.fieldOptions?.message?.paasReceiver) : []
              }
            }
          }
        }
      },
    ],
  }
  if (toNode.fieldOptions?.paasNodeId) {
    nodeItem.childNodes[0].data.executeAction.paasNodeId = toNode.fieldOptions.paasNodeId;
  }
  return nodeItem
}

function getServerJavaCode(action, fieldOptions) {
  let result = ''
  if(!action) return result
  switch(action) {
    case ConnectorOptionsActionEnum.Insert:
      result = fieldOptions['insertCode']
      break;
    case ConnectorOptionsActionEnum.Update:
      result = fieldOptions['updateCode']
      break;
    case ConnectorOptionsActionEnum.Delete:
      result = fieldOptions['deleteCode']
      break;
    default:
      break
  }
  return result
}

function setGetParentFun(item, getParent) {
  item.getParent = getParent;
  if (item.childNodes && item.childNodes.length) {
    for (let i = 0; i < item.childNodes.length; i++) {
      setGetParentFun(item.childNodes[i], getParent);
    }
  }
}

// 服务端数据转前端
function toTreeData(triggerInfo, conditionFieldList, actionAppFieldList) {
  let treeData = transformTreeData(triggerInfo, conditionFieldList, actionAppFieldList);
  function getParent() {
    return getNodeById(treeData, this.parentId);
  }
  setGetParentFun(treeData, getParent);
  return treeData;
}

let errorCooling = false
function validateError(error){
  if(errorCooling)return;
  message.error(error)
  errorCooling = true
  setTimeout(()=>{
    errorCooling = false
  }, 500)
}

// 校验单个节点数据
function validateNode(node){
  let nodeData = node.data || {}
  const isCodeWrite  = nodeData?.executeAction?.mappingType === 'code'
  switch(node.type){
    case 0:
      if(!nodeData.bizTypeId || !nodeData.bizType)
        return validateError(t('common.connector.trigger.validate.text1'));
      return true;
    case 1:
      if(!nodeData.bizActionCode || !nodeData.bizActionName)
        return validateError(t('common.connector.trigger.validate.text2'));
      if(!node.childNodes || !node.childNodes.length)
        return validateError(t('common.connector.trigger.validate.text3'));
      return true;
    case 2:
      // eslint-disable-next-line no-case-declarations
      // const isHasAppFormFieldNotSetValue = (nodeData?.conditionList || []).some(item=> {
      //   return item.some(cItem=> (!cItem.value || isEmpty(cItem.value)) && cItem.condition === ConnectorConditionTypeEnum.AppFormField)
      // });
      // if(isHasAppFormFieldNotSetValue) return validateError('存在条件选择了其他应用表单没有配置值，请检查！');
      // if(!nodeData.name)
      // return validateError('请填写触发条件规则名称');
      return true;
    case 3:
      if(!nodeData.bizTypeId || !nodeData.bizType){
        return validateError(t('common.connector.trigger.validate.text4'));
      }
      if(!nodeData.executeAction?.action){
        return validateError(t('common.connector.trigger.validate.text5'));
      }
      if(nodeData.executeAction?.action == 'INSERT' && !isCodeWrite && (nodeData.executeAction?.insertFieldOptions || []).findIndex(item=>{return !item.value && !item.rightFieldValue && item.required}) > -1){
        return validateError(t('common.connector.trigger.validate.text6'));
      }
      if(nodeData.executeAction?.action == 'UPDATE' && !isCodeWrite && (nodeData.executeAction?.updateFieldOptions?.update || []).findIndex(item=>{return !item.value && !item.rightFieldValue}) > -1){
        return validateError(t('common.connector.trigger.validate.text7'));
      }
      if(nodeData.executeAction?.action == 'DELETE' && !isCodeWrite){
        const formDeleteFields = nodeData.executeAction?.deleteFieldOptions?.delete || []
        const deleteFieldOptions = formDeleteFields.length ? formDeleteFields : nodeData?.defaultToNodeData?.fieldOptions?.delete;
        if (!deleteFieldOptions?.length) {
          return validateError(t('common.connector.trigger.validate.text8'));
        }
        const result = deleteFieldOptions.every(item => item.field ? isEmpty(item.field) : false)
        if(result) return validateError(t('common.connector.trigger.validate.text8'));
      }
      if(nodeData.executeAction?.action == 'DELETE' && ((nodeData.executeAction?.deleteFieldOptions?.message?.paasReceiver || []).length) == 0){
        return validateError(t('common.connector.trigger.validate.text9'));
      }
      return true;
    default:
      return true;
  }
}
async function validateTree(treeData){
  let flag = true
  let nodeFlag = validateNode(treeData);
  if(nodeFlag !== true) flag = false;
  if(treeData.childNodes && treeData.childNodes.length){
    let promises = treeData.childNodes.map(item=>{
      return validateTree(item)
    })
    await Promise.all(promises).then(res=>{
      if(res.indexOf(false) > -1){
        flag = false
      }
    })
    return flag
  }
  return flag

}


// 数据校验
async function validateTreeData(treeData) {
  try {
    let flag = true
    await validateTree(treeData).then(res=>{
      flag = !!res
    })
    return flag
  } catch (error) {
    console.error('数据校验错误', error)
    return false
  }
}

// 给返回的字段数组添加 supportSelect或者 supportInsert 或者 supportUpdate
function addSupportProperty(fieldList, ...keys) {
  for (let i = 0; i < fieldList.length; i++) {
    const field = fieldList[i];
    for (let j = 0; j < keys.length; j++) {
      const key = keys[j];
      field[key] = true;
    }
    if (field.children?.length) {
      addSupportProperty(field.children, ...keys);
    }
  }
  return fieldList
}

// 处理jsonArray/jsonObject类型 toFieldList 字段
function convertJsonFieldTypeToFieldList(toFieldList = []) {
  let result = []

  toFieldList.forEach(field => {
    let { enName, fieldType, children = [] } = field

    field.parentEnName = ''
    delete field.children

    result.push(field)

    if (fieldType === ConnectorFieldTypeEnum.JsonArray || fieldType === ConnectorFieldTypeEnum.JsonObject) {

      children.forEach(child => {
        child.parentEnName = enName

        // 拼接 确保唯一性
        child.enName = `${enName}-${child.enName}`
      })

      result = result.concat(...children)
    }
  })

  return result
}

function convertInsertFieldOptionsForServer(insertFieldOptions = []) {
  return insertFieldOptions
    .filter(option => !option.parentEnName)
    .map(option => {
      let { toEnName, value } = option

      let subFieldOptions = insertFieldOptions.filter(field => field.parentEnName === toEnName)

      if (subFieldOptions.length) {
        let relationShip = subFieldOptions.reduce((prev, current) => {
          // 还原拼接前的fieldName
          const originFieldName = current.toEnName.replace(`${toEnName}-`, '')

          prev[originFieldName] = {
            value: current.value[0] || '',
            valueType: current.valueType,
          }

          return prev
        }, {})

        value = JSON.stringify({
          triggerSubform: 1,
          fromEnName: value[0],
          relationShip,
        })

        option.value = [value]
      }

      return option
    })
}

const changeTreeNodeToServerNodeParams = (treeNode, action, fieldOptions = {})=> {
  const { apiId, bizTypeName } = treeNode
  treeNode.apiId = treeNode.bizTypeId || -1
  treeNode.apiAction = action
  if (treeNode.fieldOptions?.paasNodeId) {
    fieldOptions.paasNodeId = treeNode.fieldOptions.paasNodeId;
  }
  treeNode.fieldOptions = fieldOptions
  treeNode.bizTypeName = treeNode.bizTypeName.split('/')[0]

  delete treeNode.bizType
  delete treeNode.bizTypeId

  return {
    apiId,
    apiAction: action,
    fieldOptions,
    bizTypeName: bizTypeName.split('/')[0]
  }
}


export function getToStartNodeFromApiId(nodeConfig, result = []) {
  if([0, 3].includes(nodeConfig?.type)) {
    nodeConfig.data?.bizTypeId && result.push(nodeConfig.data?.bizTypeId)
  }
  if(isFunction(nodeConfig?.getParent)) {
    getToStartNodeFromApiId(nodeConfig.getParent(), result)
  }
  return result
}

export {
  getNodeById,
  toServeData,
  toTreeData,
  validateTreeData,
  addSupportProperty,
  convertJsonFieldTypeToFieldList,
  convertInsertFieldOptionsForServer,
  changeTreeNodeToServerNodeParams
}
